package com.lsh.oms.provider.service.order;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.rpc.protocol.rest.support.ContentType;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lsh.atp.api.model.hold.HoldResponse;
import com.lsh.atp.api.model.inventory.RestoreInventoryRequest;
import com.lsh.atp.api.service.inventory.IInventoryRestoreRpcService;
import com.lsh.base.common.model.CommonResult;
import com.lsh.base.lang.Exceptions;
import com.lsh.oms.api.model.order.create.CreateOrderListRequestDTO;
import com.lsh.oms.api.model.order.create.CreateOrderRequestDTO;
import com.lsh.oms.api.model.order.create.MisOrderDetailDTO;
import com.lsh.oms.api.model.order.create.MisOrderHeadDTO;
import com.lsh.oms.api.service.order.IOrderCreateRestSplitService;
import com.lsh.oms.core.constant.AtpConstant;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.enums.*;
import com.lsh.oms.core.exception.BusinessException;
import com.lsh.oms.core.exception.ExceptionStatus;
import com.lsh.oms.core.model.order.OrderDetail;
import com.lsh.oms.core.model.order.OrderDetailExtJson;
import com.lsh.oms.core.model.order.OrderHead;
import com.lsh.oms.core.model.order.OrderHeadExt;
import com.lsh.oms.core.proxy.handler.AsyncTaskHandler;
import com.lsh.oms.core.proxy.service.EsProxy;
import com.lsh.oms.core.proxy.service.MisProxy;
import com.lsh.oms.core.service.order.OrderCreateService;
import com.lsh.oms.core.service.order.OrderCreateValidateService;
import com.lsh.oms.core.service.order.OrderQueryService;
import com.lsh.oms.core.service.sms.ShortMessageHandler;
import com.lsh.oms.core.utils.IdGenerator;
import com.lsh.oms.core.utils.OMSUtils;
import com.lsh.oms.core.utils.ShopCheckUtils;
import com.lsh.oms.provider.service.BaseService;
import com.lsh.oms.provider.utils.ValidationBeanUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.math.BigDecimal;
import java.util.*;

/**
 * Project Name: lsh-oms
 *
 * @author peter
 * on 18/12/23.
 * 北京链商电子商务有限公司
 * Package
 * desc:
 */
@Service(protocol = "rest", timeout = 30000)
@Path("order/split")
@Consumes({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
@Produces({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
public class OrderCreateRestSplitServiceImpl extends BaseService implements IOrderCreateRestSplitService {

    private final static String SUCCESS = "success";

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private OrderCreateService orderCreateService;

    @Autowired
    private IInventoryRestoreRpcService restoreService;

    @Autowired
    private OrderQueryService orderQueryService;

    @Autowired
    private EsProxy esProxy;

    @Autowired
    private MisProxy misProxy;

    @Autowired
    private OrderCreateValidateService validateService;

    @Autowired
    private ShortMessageHandler shortMessageHandler;

    /**
     * 创建订单接口
     *
     * @param orderRequestDTO 下单参数
     * @return
     */
    @POST
    @Path("create")
    @Override
    public CommonResult<List<String>> createOrder(CreateOrderRequestDTO orderRequestDTO) {
        long createTsS = System.currentTimeMillis();
        if (null == orderRequestDTO || CollectionUtils.isEmpty(orderRequestDTO.getMisOrderList())) {
            return new CommonResult<>(ReturnCode.REQUEST_FAIL, "create order params is null! or 下单请求参数错误", Collections.singletonList(""));
        }

        Long venderId = this.getVenderId();

        String misLogSign = orderRequestDTO.getLogSign();
        logger.info(misLogSign + " : parent order create {} ", JSON.toJSONString(orderRequestDTO));

        if (orderRequestDTO.getMisOrderList().size() != 1) {
            return new CommonResult<>(ReturnCode.REQUEST_FAIL, "下单请求参数错误 misOrderList is not one ");
        }
        CommonResult commonResult = new CommonResult<>();
        try {
            MisOrderHeadDTO misOrderHeadDTO = orderRequestDTO.getMisOrderList().get(0);
            logger.info("misOrderHeadDTO is {}", JSON.toJSONString(misOrderHeadDTO));
            misOrderHeadDTO.setVenderId(venderId);
            ValidationBeanUtils.checkRequiredFields(misOrderHeadDTO);

            OrderHead head = this.builderOrderHeadInfo(misOrderHeadDTO, misLogSign);

            String poOrderFlag = misOrderHeadDTO.getPoOrderFlag();
            if (StringUtils.isBlank(poOrderFlag)) {
                poOrderFlag = "0";
            }

            logger.info("order create json OrderHead {} ", JSON.toJSONString(head));
            commonResult = validateService.validateAll(head, misOrderHeadDTO, misLogSign);

            if (!SUCCESS.equals(commonResult.getMessage())) {
                return commonResult;
            }
            //库存扣减
            if (subtractStockRequired(misOrderHeadDTO)) {
                CommonResult<List<String>> atpRet = validateService.checkAndSubtractStock(head, misLogSign);
                if (!CommonResult.SUCCESS.equals(atpRet.getCode())) {
                    return atpRet;
                }
            }

            StringBuilder logSign = this.buildLogSign(head, misLogSign);
            int logSignLen = logSign.length();

            Long orderRes;
            logger.info(logSign.append("inset into db start").toString());
            logSign.setLength(logSignLen);
            long insertDbTsS = System.currentTimeMillis();
            List<String> misAndOrderCodeList = new ArrayList<>(2);
            try {
                orderRes = this.orderCreateService.create(head, poOrderFlag);

                Map<String, String> orderCodes = new HashMap<>(3);
                orderCodes.put("mis_order_id", head.getMisOrderNo());
                orderCodes.put("order_id", orderRes + "");
                orderCodes.put("is_valid", head.getValid().toString());

                misAndOrderCodeList.add(JSON.toJSONString(orderCodes));
            } catch (Exception e) {
                Exceptions.printStackTraceLineByLine(e);
                logger.error("mis log sign: " + misLogSign + ", create order: " + head.getOrderCode() + " failed, exception: " + e.getMessage(), e);
                commonResult = dbException(head, misLogSign);
                logger.error(logSign.append(e.getMessage()).toString(), e);
                logSign.setLength(logSignLen);
                logger.info(logSign.append("【创建失败】，新建订单请求共耗时：").append((System.currentTimeMillis() - insertDbTsS)).append("ms").toString());
                logSign.setLength(logSignLen);

                return commonResult;
            }
            long insertDbTsE = System.currentTimeMillis();
            logger.info(logSign.append("inset into db end, 耗时：").append(insertDbTsE - insertDbTsS).append("ms").toString());
            logSign.setLength(logSignLen);

            String logSignForAsyncTask = logSign.toString().substring(0, logSignLen - 1);

            AsyncTaskHandler.executeAsyncTask(esProxy.newAsyncCreateTask(EsProxy.transformToOrderHeadForEs(head, misOrderHeadDTO), logSignForAsyncTask));
            // TODO 关闭分控
//            if (!poOrderFlag.equals(PoOrderFlag.PRE_ORDER.getType())) {
//                AsyncTaskHandler.executeAsyncTask(riskProxy.newAsyncTask(head, logSignForAsyncTask));
//            }

            long createTsE = System.currentTimeMillis();
//            HashMap<String, Long> times = (HashMap<String, Long>) commonResult.getData();
            logger.info(logSign.append("创建成功，新建订单请求共耗时：").append(createTsE - createTsS).append("ms").toString());
            logSign.setLength(logSignLen);
            commonResult = new CommonResult<>(ReturnCode.REQUEST_SUCCESS, "success", misAndOrderCodeList);
        } catch (BusinessException e) {
            Exceptions.printStackTraceLineByLine(e);
            commonResult.setCode(e.getCode());
            commonResult.setMessage(e.getMessage());
            logger.error("业务异常code : " + e.getCode() + ",异常信息: " + e.getMessage(), e);
        } catch (Exception e) {
            Exceptions.printStackTraceLineByLine(e);
            commonResult.setCode(ExceptionStatus.E3001001.getCode());
            commonResult.setMessage(ExceptionStatus.E3001001.getMessage());
            logger.error("系统异常code : " + ExceptionStatus.E3001001.getCode(), e);
        }

        return commonResult;
    }

    private boolean subtractStockRequired(MisOrderHeadDTO orderRequest) {
        return !orderRequest.getPoOrderFlag().equals(PoOrderFlag.PRE_ORDER.getType()) && !orderRequest.aggregate();
    }

    /**
     * 拆单创建订单接口
     *
     * @param orderListRequestDTO 拆单参数
     * @return
     */
    @Override
    @POST
    @Path("createChildrenList")
    public CommonResult<List<String>> createSubOrder(CreateOrderListRequestDTO orderListRequestDTO) {

        logger.info("order createChildrenList params is --> {}", JSON.toJSONString(orderListRequestDTO));
        List<MisOrderHeadDTO> orderHeadDTOList = orderListRequestDTO.getMisOrderList();
        if (CollectionUtils.isEmpty(orderHeadDTOList)) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "order createChildrenList params is null！");
        }

        if (orderHeadDTOList.size() < 2) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "子单创建个数最小为1，请检查数据信息");
        }

        // 生成父订单号的策略,以及日志前缀
        final String logSignParam = orderListRequestDTO.getLogSign();
        StringBuilder logSign = new StringBuilder(logSignParam).append("_创建订单 ：");
        CommonResult<List<String>> commonResult = new CommonResult<>();
        try {
            //子单列表
            List<MisOrderHeadDTO> childrenOrderHeadDTOList = new ArrayList<>();
            for (MisOrderHeadDTO misOrderHeadDTO : orderHeadDTOList) {
                String misParentOrderNo = misOrderHeadDTO.getMisParentOrderNo();
                if (StringUtils.isNotBlank(misParentOrderNo) && !misParentOrderNo.equals("0")) {
                    childrenOrderHeadDTOList.add(misOrderHeadDTO);
                }
            }

            Long parentOrderCode = orderListRequestDTO.getParentOrderCode();
            if (parentOrderCode == null) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "父单参数有误缺少 MisOrderNo");
            }

            OrderHead parentOrderHead = this.orderQueryService.findByCode(parentOrderCode, true, false);
            if (org.springframework.util.ObjectUtils.isEmpty(parentOrderHead)) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "父单订单信息不存在，请联系相关人员或重试");
            }
            List<OrderHead> orderHeadList = this.orderQueryService.findByParentOrderCode(parentOrderHead.getOrderCode(), false, false);

            // 接口幂等处理 子单已创建
            if (!CollectionUtils.isEmpty(orderHeadList)) {
                List<String> misAndOrderCodeList = new ArrayList<>(orderHeadList.size());
                for (OrderHead order : orderHeadList) {
                    Map<String, String> orderCodes = new HashMap<>(OMSUtils.mapSize(orderHeadList.size()));
                    orderCodes.put("mis_order_id", order.getMisOrderNo());
                    orderCodes.put("order_id", order.getOrderCode().toString());
                    orderCodes.put("is_valid", order.getValid().toString());

                    misAndOrderCodeList.add(JSON.toJSONString(orderCodes));
                }

                commonResult.setCode(ReturnCode.REQUEST_SUCCESS);
                commonResult.setMessage("success");
                commonResult.setData(misAndOrderCodeList);

                return commonResult;
            }
            // 写入ES Map集合
            HashMap<OrderHead, MisOrderHeadDTO> omsOrder2MisOrderMap = new HashMap<>((int) ((childrenOrderHeadDTOList.size() / 0.75) + 1));
            Long venderId = this.getVenderId();
            for (MisOrderHeadDTO misOrderHeadDTO : childrenOrderHeadDTOList) {
                misOrderHeadDTO.setVenderId(venderId);
                ValidationBeanUtils.checkRequiredFields(misOrderHeadDTO);
                OrderHead orderHead = this.builderOrderInfo(misOrderHeadDTO, logSignParam, parentOrderHead);
                String orderDc = misOrderHeadDTO.getDcCode();
                if (StringUtils.isBlank(orderDc)) {
                    throw new BusinessException(ReturnCode.REQUEST_FAIL, "orderDc 不能为空 创建子单列表失败");
                }
                JSONObject headExt = JSON.parseObject(orderHead.getExt());
                // TODO 可优化
                OrderDetail detail = orderHead.getDetails().get(0);
                JSONObject detailExt = JSON.parseObject(detail.getDetailExt());
                String providerId = detailExt.getString("providerId");
                String providerName;
                if (StringUtils.isBlank(providerId)) {
                    throw new BusinessException(ReturnCode.REQUEST_FAIL, "providerId 不能为空 创建子单列表失败");
                }
                providerName = this.misProxy.requestProviderName(providerId, venderId);
                headExt.put("providerId", providerId);
                headExt.put("providerName", providerName);

                orderHead.setExt(headExt.toJSONString());
                omsOrder2MisOrderMap.put(orderHead, misOrderHeadDTO);
            }
            // TODO 云仓相关子单 可以去掉
            for (OrderHead orderHead : omsOrder2MisOrderMap.keySet()) {

                JSONObject extJson = JSON.parseObject(orderHead.getExt());
                if (null == extJson) {
                    throw new BusinessException(ReturnCode.REQUEST_FAIL, "extJson 不能为空 创建子单列表失败");
                }
                extJson.put("parentHaveCloudChildren", 0);
                orderHead.setExt(extJson.toJSONString());
            }

            // 批量创建订单
            logger.info("{} 创建子单开始 父单号{},子单个数 {}", new Object[]{logSign.toString(), parentOrderHead.getOrderCode(), omsOrder2MisOrderMap.size()});
            List<String> orderRes = this.orderCreateService.createSplitList(parentOrderHead, omsOrder2MisOrderMap.keySet(), logSign.toString(), venderId);
            logger.info("{} 创建子单完成 返回结果 {}", new Object[]{logSign.toString(), JSON.toJSONString(orderRes)});

            if (CollectionUtils.isEmpty(orderRes)) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "创建子单列表失败");
            }

            // 3000区域下，云仓的订单，需要在订单行项目上，填充未税成本、含税成本、税率、扣点等信息
//            this.needInsertFillTaxRateTask(omsOrder2MisOrderMap);

            commonResult.setCode(ReturnCode.REQUEST_SUCCESS);
            commonResult.setMessage("success");
            commonResult.setData(orderRes);

            this.dealEs(parentOrderHead, omsOrder2MisOrderMap, logSignParam);
        } catch (BusinessException e) {
            Exceptions.printStackTraceLineByLine(e);
            commonResult.setCode(e.getCode());
            commonResult.setMessage(e.getMessage());
            logger.error("业务异常code : " + e.getCode() + ",异常信息: " + e.getMessage(), e);
        } catch (Exception e) {
            Exceptions.printStackTraceLineByLine(e);
            commonResult.setCode(ExceptionStatus.E3001001.getCode());
            commonResult.setMessage(ExceptionStatus.E3001001.getMessage());
            logger.error("系统异常code : " + ExceptionStatus.E3001001.getCode(), e);
        }

        return commonResult;
    }

//    /**
//     * 3000区域下，云仓的订单，需要在订单行项目上，填充未税成本、含税成本、税率、扣点等信息
//     *
//     * @param omsOrder2MisOrderMap
//     */
//    private void needInsertFillTaxRateTask(Map<OrderHead, MisOrderHeadDTO> omsOrder2MisOrderMap) {
//        for (Map.Entry<OrderHead, MisOrderHeadDTO> entry : omsOrder2MisOrderMap.entrySet()) {
//            OrderHead orderHead = entry.getKey();
//            try {
//                int userType = OrderFactory.getUserType(orderHead);
//                if (UserType.KA.getIndex() == userType) {
//                    this.orderCreateService.addFillPriceAndRateTask(String.valueOf(orderHead.getOrderCode()), orderHead.getVenderId());
//                }
//            } catch (Exception e) {
//                logger.error("判断订单，是否是KA卖票异常", e);
//            }
//        }
//    }

    /**
     * 操作ES
     *
     * @param parentOrderHead 父单号
     * @param orderMap4ES     es
     * @param logSignParam    唯一标识
     */
    private void dealEs(OrderHead parentOrderHead, Map<OrderHead, MisOrderHeadDTO> orderMap4ES, String logSignParam) {
        try {
            AsyncTaskHandler.executeAsyncTask(esProxy.asyncDeleteIndexTask(EsProxy.transformToOrderHeadForEs(parentOrderHead), parentOrderHead.getOrderCode() + ""));

            for (Map.Entry<OrderHead, MisOrderHeadDTO> entry : orderMap4ES.entrySet()) {
                AsyncTaskHandler.executeAsyncTask(esProxy.newAsyncCreateTask(EsProxy.transformToOrderHeadForEs(entry.getKey(), entry.getValue()), logSignParam));
                // 通知供商冻品订单
                OrderHead orderHead = entry.getKey();
                if (orderHead.getStorageType() == StorageType.LOW.getIndex()) {
                    shortMessageHandler.pushNotify(entry.getKey());
                }
            }
        } catch (Exception e) {
            Exceptions.printStackTraceLineByLine(e);
            logger.error("操作ES异常,异常信息: ", e);
        }
    }

    /**
     * 组装订单信息
     *
     * @param misOrderHeadDTO 组装订单信息
     * @return
     */
    private OrderHead builderOrderHeadInfo(MisOrderHeadDTO misOrderHeadDTO, String misLogSign) {

        Integer timestamp = (int) (System.currentTimeMillis() / 1000);
        OrderHead targetOrderHead = new OrderHead();

        BeanUtils.copyProperties(misOrderHeadDTO, targetOrderHead);

        targetOrderHead.setVenderId(misOrderHeadDTO.getVenderId());

        targetOrderHead.setOrderClass(orderClass(misOrderHeadDTO));
        targetOrderHead.setOrderCode(orderCode(misOrderHeadDTO));

        targetOrderHead.setPayStatus(PayStatus.NOT_PAID.getValue());
        targetOrderHead.setPayReliefAmout(BigDecimal.ZERO);
        targetOrderHead.setActualPayAmount(BigDecimal.ZERO);
        //根订单
        targetOrderHead.setParentOrderCode(0L);
        targetOrderHead.setValid(YN.Y.getValue());
        targetOrderHead.setCreateTime(timestamp);
        targetOrderHead.setUpdateTime(timestamp);

        if (targetOrderHead.getRegionCode().equals(RegionCode.BEIJING_KA.getCode())) {
            //判断销售区域的
            String saleAreaCode = "5000";
            if (StringUtils.isBlank(misOrderHeadDTO.getSaleAreaCode())) {
                targetOrderHead.setSaleAreaCode(saleAreaCode);
            }
        }
        String poOrderFlag = misOrderHeadDTO.getPoOrderFlag();
        if (StringUtils.isBlank(poOrderFlag)) {
            poOrderFlag = "0";
//            throw new BusinessException(ReturnCode.REQUEST_FAIL, "poOrderFlag 不能为空");
        }

        String remark = misOrderHeadDTO.getRemarks();

        if (StringUtils.isBlank(remark)) {
            remark = "";
        }

        // head 内部 ext
        JSONObject createExt = new JSONObject();
        createExt.put("marketName", misOrderHeadDTO.getMarketName());
        createExt.put("username", misOrderHeadDTO.getUsername());
        createExt.put("adminName", misOrderHeadDTO.getAdminName());
        createExt.put("deviceId", misOrderHeadDTO.getDeviceId());
        createExt.put("logSign", misLogSign);
        createExt.put("position", JSON.toJSONString(misOrderHeadDTO.getPosition()));
        createExt.put("remark", remark);
        createExt.put("MisParentOrderNo", ObjectUtils.toString(misOrderHeadDTO.getMisParentOrderNo(), "0"));
        createExt.put("poOrderFlag", poOrderFlag);
        createExt.put("poId", ObjectUtils.toString(misOrderHeadDTO.getPoId(), ""));
        createExt.put("supplierCode", ObjectUtils.toString(misOrderHeadDTO.getSupplierCode(), ""));
        targetOrderHead.setExt(createExt.toJSONString());

        // headExt 信息
        OrderHeadExt headExt = new OrderHeadExt();
        BeanUtils.copyProperties(misOrderHeadDTO, headExt);

        headExt.setIp(misOrderHeadDTO.getClientIp());
        headExt.setActivedAt(misOrderHeadDTO.getOrderTime());
        headExt.setFromType(misOrderHeadDTO.getClientType());
        headExt.setOfcId(0L);
        headExt.setOfcStatus(0);
        headExt.setRemarks(remark);
        //不在使用
        headExt.setIsRoot(YN.N.getValue());
        headExt.setIsComment(YN.N.getValue());
        headExt.setDelayRemark(0);

        targetOrderHead.setExtObject(headExt);

        List<MisOrderDetailDTO> details = misOrderHeadDTO.getDetails();
        boolean itemCodeFlag = this.parseDto2orderDetails(details, targetOrderHead, poOrderFlag, misOrderHeadDTO.getVenderId());
        if (!itemCodeFlag) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "【itemCode】订单内商品信息错误，请联系客服。");
        }
        //初始化订单状态
        targetOrderHead.setIsMp(YN.Y.getValue());
        Integer isNewUser = misOrderHeadDTO.getIsNewUser();

        if (poOrderFlag.equals(PoOrderFlag.PRE_ORDER.getType())) {
            targetOrderHead.setOrderStatus(OrderStatus.ORDER_PRE.getIndex());
            return targetOrderHead;
        }

        if (null == isNewUser || YN.Y.getValue().equals(isNewUser)) {
            targetOrderHead.setOrderStatus(OrderStatus.ORDER_NO_EDIT.getIndex());
            return targetOrderHead;
        }

        boolean passFlag = false;
        try {
            passFlag = ShopCheckUtils.checkMarketInfo4Position(targetOrderHead.getAddressInfo());
        } catch (Throwable throwable) {
            logger.error("check market info for position error!!", throwable);
        }
        if (passFlag) {
            targetOrderHead.setOrderStatus(OrderStatus.ORDER_SPLIT_CHECK.getIndex());
        } else {
            targetOrderHead.setOrderStatus(OrderStatus.ORDER_NO_EDIT.getIndex());
        }

        return targetOrderHead;
    }

    private Long orderCode(MisOrderHeadDTO orderRequest) {
        return orderRequest.aggregate() ? orderRequest.getSpecifiedOrderCode() : IdGenerator.genId();
    }

    private String orderClass(MisOrderHeadDTO orderRequest) {
        return StringUtils.isNotBlank(orderRequest.getOrderClass()) ? orderRequest.getOrderClass() : "NORMAL";
    }

    /**
     * 组装订单信息
     *
     * @param misOrderHeadDTO
     * @param misLogSign
     * @param parentOrderHead
     * @return
     */
    private OrderHead builderOrderInfo(MisOrderHeadDTO misOrderHeadDTO, String misLogSign, OrderHead parentOrderHead) {

        Long orderCode = IdGenerator.genId();
        Integer timestamp = (int) (System.currentTimeMillis() / 1000);
        OrderHead targetOrderHead = new OrderHead();
        BeanUtils.copyProperties(misOrderHeadDTO, targetOrderHead);
        targetOrderHead.setOrderCode(orderCode);
        targetOrderHead.setValid(YN.Y.getValue());

        targetOrderHead.setVenderId(misOrderHeadDTO.getVenderId());

        targetOrderHead.setSaleAreaCode(parentOrderHead.getSaleAreaCode());
        targetOrderHead.setPayType(parentOrderHead.getPayType());
        targetOrderHead.setParentOrderCode(parentOrderHead.getOrderCode());
        targetOrderHead.setPayChannel(parentOrderHead.getPayChannel());
        targetOrderHead.setPaySequence(parentOrderHead.getPaySequence());
        targetOrderHead.setPayStatus(parentOrderHead.getPayStatus());

        targetOrderHead.setPayReliefAmout(BigDecimal.ZERO);
        if (!parentOrderHead.getPayType().equals(PayType.PAY_ON_DELIVERY.getValue())) {
            targetOrderHead.setActualPayAmount(targetOrderHead.getExpectPayAmount());
        } else {
            targetOrderHead.setActualPayAmount(BigDecimal.ZERO);
        }

        targetOrderHead.setCreateTime(timestamp);
        targetOrderHead.setUpdateTime(timestamp);
        int parentPayType = parentOrderHead.getPayType();
        int payType = misOrderHeadDTO.getPayType();

        if (parentPayType != payType) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "payType 与父单的payType 不一致。");
        }

        String remark = misOrderHeadDTO.getRemarks();
        if (StringUtils.isBlank(remark)) {
            remark = "";
        }
        String poOrderFlag = misOrderHeadDTO.getPoOrderFlag();
        //天津的订单 oms 不会拆单
        if (StringUtils.isBlank(poOrderFlag)) {
            poOrderFlag = "0";
        }

        // head 内部 ext
        JSONObject createExt = new JSONObject();
        createExt.put("marketName", misOrderHeadDTO.getMarketName());
        createExt.put("username", misOrderHeadDTO.getUsername());
        createExt.put("adminName", misOrderHeadDTO.getAdminName());
        createExt.put("deviceId", misOrderHeadDTO.getDeviceId());
        createExt.put("logSign", misLogSign);
        createExt.put("position", JSON.toJSONString(misOrderHeadDTO.getPosition()));
        createExt.put("orderDc", misOrderHeadDTO.getDcCode());
        createExt.put("MisParentOrderNo", ObjectUtils.toString(misOrderHeadDTO.getMisParentOrderNo(), "0"));
        createExt.put("remark", remark);
        createExt.put("poOrderFlag", poOrderFlag);
        createExt.put("poId", ObjectUtils.toString(misOrderHeadDTO.getPoId(), ""));
        createExt.put("supplierCode", ObjectUtils.toString(misOrderHeadDTO.getSupplierCode(), ""));
        targetOrderHead.setExt(createExt.toJSONString());

        if (StringUtils.isBlank(misOrderHeadDTO.getDcCode())) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "orderDc 不能为空 创建子单列表失败");
        }

        // headExt 信息
        OrderHeadExt headExt = new OrderHeadExt();

        BeanUtils.copyProperties(misOrderHeadDTO, headExt);

        headExt.setIp(misOrderHeadDTO.getClientIp());
        headExt.setActivedAt(misOrderHeadDTO.getOrderTime());
        headExt.setFromType(misOrderHeadDTO.getClientType());
        headExt.setOfcId(0L);
        headExt.setOfcStatus(0);
        headExt.setDelayRemark(0);
        headExt.setIsComment(YN.N.getValue());
        headExt.setRemarks(remark);
        //不在使用
        headExt.setIsRoot(YN.N.getValue());

        targetOrderHead.setExtObject(headExt);

        List<MisOrderDetailDTO> details = misOrderHeadDTO.getDetails();

        boolean itemCodeFlag = this.parseDto2orderDetails(details, targetOrderHead, poOrderFlag, misOrderHeadDTO.getVenderId());
        if (!itemCodeFlag) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "【itemCode】订单内商品信息错误，请联系客服。");
        }

        targetOrderHead.setIsMp(parentOrderHead.getIsMp());
        targetOrderHead.setOrderStatus(OrderStatus.ORDER_COMMITING_OFC.getIndex());

        return targetOrderHead;
    }

    /**
     * 解析JSON，设置订单明细信息
     *
     * @param detailsDto detailsDto
     * @param head       void
     */
    private boolean parseDto2orderDetails(List<MisOrderDetailDTO> detailsDto, OrderHead head, String poOrderFlag, Long venderId) {
        Long orderCode = head.getOrderCode();
        Integer createTime = head.getCreateTime();
        BigDecimal totalQty = BigDecimal.ZERO;
        BigDecimal totalAmt = BigDecimal.ZERO;
        BigDecimal totalSkuQty = BigDecimal.ZERO;
        List<OrderDetail> details = new ArrayList<>(detailsDto.size());
        Map<Integer, Integer> num = new HashMap<>((int) (detailsDto.size() / (0.75) + 1));
        StringBuilder itemCodes = new StringBuilder();
        for (MisOrderDetailDTO orderDetailDTO : detailsDto) {

            ValidationBeanUtils.checkRequiredFields(orderDetailDTO);
            BigDecimal price = orderDetailDTO.getPrice();
            BigDecimal quantity = orderDetailDTO.getQuantity();
            Long goodsCode = orderDetailDTO.getGoodsCode();

            if ((!poOrderFlag.equals(PoOrderFlag.PRE_ORDER.getType())) && quantity.compareTo(BigDecimal.ZERO) <= 0) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "goodsCode : " + goodsCode + " 的下单数量是0");
            }
            // 2018-08-30 云仓需求所加
            String providerId = orderDetailDTO.getProviderId();
            String itemNo = orderDetailDTO.getItemNo();
            Integer saleModel = orderDetailDTO.getSaleModel();

            if (StringUtils.isBlank(providerId)) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "providerId 订单详情供商信息不存在");
            }

            if (StringUtils.isBlank(itemNo)) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "itemNo 订单详情供商信息不存在");
            }

            if (null == saleModel) {
                throw new BusinessException(ReturnCode.REQUEST_FAIL, "saleModel 订单详情供商信息不存在");
            }

            OrderDetail detail = new OrderDetail();
            BeanUtils.copyProperties(orderDetailDTO, detail);
            Integer itemCode = detail.getItemCode();
            if (null == itemCode) {
                itemCode = 0;
            }
            detail.setItemCode(itemCode);
            detail.setVenderId(venderId);

            if (itemCode > 0) {
                Integer value = num.get(itemCode);
                if (null != value) {
                    itemCodes.append(value);
                }
                num.put(itemCode, itemCode);
            }

            String goodsExtAttrs = ObjectUtils.toString(orderDetailDTO.getGoodsExtAttrs());
            Long packageCode = orderDetailDTO.getPackageCode();
            Long giftSrcCode = orderDetailDTO.getGiftSrcCode();

            detail.setGoodsExtAttrs(goodsExtAttrs);
            detail.setPackageCode(packageCode == null ? 0L : packageCode);
            detail.setGiftSrcCode(giftSrcCode == null ? 0L : giftSrcCode);
            detail.setCreateTime(createTime);
            detail.setUpdateTime(createTime);
            detail.setOrderCode(orderCode);

            BigDecimal realQty = orderDetailDTO.getRealQty();
            BigDecimal money = price.multiply(quantity);

            detail.setDetailExt(this.initDetailExtOne(head, orderDetailDTO, money));

            details.add(detail);

            totalQty = totalQty.add(quantity);
            totalAmt = totalAmt.add(money);
            totalSkuQty = totalSkuQty.add(realQty);
        }

        head.setGoodsTotalQuantity(totalQty);
        head.setGoodsTotalAmount(totalAmt);
        head.setDetails(details);
        boolean detailFlag = true;
        if (!CollectionUtils.isEmpty(num)) {
            if (num.size() != details.size()) {
                detailFlag = false;
                logger.info("itemCode 订单内部不唯一，itemCodes {}", itemCodes.toString());
            }
        }

        return detailFlag;
    }

    /**
     * @param head
     * @param orderDetailDTO
     * @param money
     * @return
     */
    private String initDetailExtOne(OrderHead head, MisOrderDetailDTO orderDetailDTO, BigDecimal money) {
        // 来自于 detail 拆单
        OrderDetailExtJson orderDetailExtJson = new OrderDetailExtJson();
        BeanUtils.copyProperties(orderDetailDTO, orderDetailExtJson);
        orderDetailExtJson.setUid(head.getUserCode());
        orderDetailExtJson.setZoneId(head.getRegionCode());
        orderDetailExtJson.setMoney(money);
        orderDetailExtJson.setExt("{}");
        orderDetailExtJson.setOfcId(0L);
        orderDetailExtJson.setOfcStatus(0);
        orderDetailExtJson.setStatus(1);
        orderDetailExtJson.setSaleModel(orderDetailDTO.getSaleModel());

        if (null == orderDetailDTO.getIsWeighingGoods()) {
            orderDetailExtJson.setIsWeighingGoods(0);
        }

        return JSON.toJSONString(orderDetailExtJson);
    }


    /**
     * 创建订单失败回滚
     *
     * @param head       head
     * @param misLogSign misLogSign
     * @return
     */
    private CommonResult<List<String>> dbException(OrderHead head, String misLogSign) {
        StringBuilder logSign = this.buildLogSign(head, misLogSign);
        int logSignIndex = logSign.length();

        long atpStarRestoreTime = System.currentTimeMillis();
        // 释放库存
        RestoreInventoryRequest request = new RestoreInventoryRequest();
        request.setChannel(AtpConstant.ATP_CHANNEL_CODE);
        request.setSequence(head.getOrderCode().toString());
        logger.info(logSign.toString() + " : atp request is - " + JSON.toJSONString(request));

        try {
            HoldResponse resp = restoreService.restoreInventory(request);

            logger.info(logSign.toString() + " : atp response is - " + resp.getStatus() + " , msg is " + resp.getMeg());
            boolean atpFlag = resp.getStatus() == 0 || resp.getStatus().equals(2001006);

            logSign.setLength(logSignIndex);
            logger.info(logSign.append("创建订单atp释放耗时:").append((System.currentTimeMillis() - atpStarRestoreTime)).append("ms").toString());
            logSign.setLength(logSignIndex);
            logger.info(logSign.append("创建失败,释放库存结果:").append(atpFlag).toString());
        } catch (Exception e) {
            Exceptions.printStackTraceLineByLine(e);
            logger.error(logSign.append(" restore inventory Exception : ").append(e.getMessage()).toString(), e);
        }

        Map<String, String> map = new HashMap<>(4);
        map.put("misOrderNo", head.getMisOrderNo());
        return new CommonResult<>(ReturnCode.CREATE_ORDER_IS_REPEAT, "创建订单失败", Collections.singletonList(JSON.toJSONString(map)));
    }

    /**
     * @param head
     * @param misLogSign
     * @return
     */
    private StringBuilder buildLogSign(OrderHead head, String misLogSign) {
        StringBuilder builder = new StringBuilder(misLogSign);
        builder.append(" 创建订单_").append(head.getMisOrderNo()).append("_").append(head.getOrderCode()).append("：");
        return builder;
    }

}
